<template>
  <div>
    <div class="margin-l-20 margin-r-20">
      <a-tabs
          v-if="!isDetail"
          tab-position="top"
          v-model="selTab"
          type="editable-card"
          :hideAdd="isDetail"
          :style="{ height: '50px' }"
          @edit="onEdit"
      >
        <a-tab-pane v-for="tab in tabList" :key="tab.name" :tab="tab.label" :closable="!isDetail" />
      </a-tabs>
      <a-tabs
          v-else
          tab-position="top"
          v-model="selTab"
          type="editable-card"
          :hideAdd="isDetail"
          :style="{ height: '50px' }"
          @edit="onEdit"
      >
        <a-tab-pane v-for="tab in tabList" :key="tab.name" :closable="!isDetail">
          <template v-slot:tab>
            <div>
              {{ tab.label }}
              <q-icon v-if="selTab===tab.name" name="iconfont icontubiao-58" class="icon margin-l-5" @click="toDetail">
                <q-tooltip>跳转到实时数据</q-tooltip>
              </q-icon>
            </div>
          </template>
        </a-tab-pane>
      </a-tabs>
    </div>
    <div class="margin-t-10 margin-b-10 margin-r-20 margin-l-20 flex justify-between items-center" v-if="!isDetail">
      <div>
        <q-btn class="btn margin-r-10"
               outline
               color="primary"
               label="添加"
               :disable="!selTab"
               @click="createOrEdit('add')"/>
        <q-btn class="btn margin-r-10" outline color="primary" @click="download">下载模版</q-btn>
        <upload-btn v-if="selTab" @uploadUrlSuccess="uploadUrlSuccess" ref="uploadBtn"/>
        <q-btn class="btn" outline color="primary" @click="exportExcel" :disable="tableData.length === 0 || exportLoading" :loading="exportLoading">导出</q-btn>
      </div>
      <div>
        <i class="iconfont icontubiao-28 margin-r-5"></i>每个设备最多支持500个点位
      </div>
    </div>
    <q-table
      :data="tableData"
      :columns="columns"
      row-key="id"
      :style="{height: height}"
      class="myTable scroll"
      :class="[isDetail ? '' : 'stick-last-col']"
      :loading="isTableLoading"
      :pagination.sync="pagination"
      :hide-bottom="tableData.length > 0"
      color="primary"
    >
      <template v-slot:body-cell-operations="props">
        <q-td class="operations" style="width: 100px">
          <div class="btn-group" style="text-align: center">
            <table-btn :disable="props.row.serviceTypeId === 'DevPower'" btnType="edit" @click="createOrEdit('edit', props.row)"/>
            <table-btn :disable="props.row.serviceTypeId === 'DevPower'" btnType="delete" @click="deletePoint(props.row)"/>
          </div>
        </q-td>
      </template>
    </q-table>
    <div>
      <pagination
        class="pagination"
        v-model="pagination.page"
        :page-size="pagination.rowsPerPage"
        :total="pagination.rowsNumber"
        @changePageSize="onPageSizeChange"
        @changePage="onPageChange"
      />
    </div>
    <AddEditPointDialog v-if="!isDetail" :controllerType="controllerType" :deviceTypeOptions="deviceTypeOptions" :tableDataAll="tableDataAll" ref="addEditPointDialog" @add="addData" @edit="editData" />

    <SetDeviceDialog :tabList="tabList" :controllerType="controllerType" :deviceTypeOptions="deviceTypeOptions" v-if="!isDetail" :addDeviceDialog="addDeviceDialog" @close="addDeviceDialog=false" @addDevice="addDevice" />

    <SetProductDialog v-if="!isDetail" :deviceTypeOptions="deviceTypeOptions" :setProductDialog="setProductDialog" @close="setProductDialog=false" @submit="submitDownload" />
  </div>
</template>

<script>
import AddEditPointDialog from './add-edit-point-dialog'
import SetDeviceDialog from './set-device-dialog'
import SetProductDialog from './set-product-dialog'
import Pagination from 'src/components/pagination'
import {
  downloadEnergyPointTemplate,
  downloadPointTemplate, exportEnergyPoint,
  exportPlcPoint,
  getBindPoint,
  getBoxProducts, getPlcDeviceByBoxId, getPlcPoint, getUserByDeviceId, uploadEnergyPointTemplate,
  uploadPointTemplate
} from '../../../../../boot/miot/plc-list'
import { dataTypeOption, dataTypeReportOption, partcountObj, reportTypeOption } from './constant'

export default {
  name: 'point-table',
  components: {
    AddEditPointDialog,
    Pagination,
    SetDeviceDialog,
    SetProductDialog
  },
  props: {
    isDetail: {
      type: Boolean,
      default: false
    },
    height: {
      type: String,
      default: '300px'
    },
    controllerType: {
      type: String,
      default: ''
    },
    boxDriverId: {
      type: String,
      default: ''
    },
    driverParams: {
      type: Object,
      default: () => {}
    },
    isPreVersion: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      activeKey: '',
      submitting: false,
      isTableLoading: false,
      tableDataAll: [],
      deviceTypeOptions: [],
      columnsAll: [
        { name: 'addr', label: '点位地址', align: 'left', field: 'addr' },
        { name: 'reportTypeName', label: '上报类型', align: 'left', field: 'reportTypeName' },
        { name: 'dataTypeName', label: '数据类型(采集)', align: 'left', field: 'dataTypeName' },
        { name: 'deviceTypeName', label: '物模型', align: 'left', field: 'deviceTypeName' },
        { name: 'relaPoint', label: '关联点位', align: 'left', field: 'relaPoint' },
        { name: 'repName', label: '上报名称', align: 'left', field: 'repName' },
        { name: 'partcountName', label: '清零/累加', align: 'left', field: 'partcountName' },
        { name: 'repDataTypeName', label: '数据类型(上报)', align: 'left', field: 'repDataTypeName' },
        { name: 'unit', label: '单位', align: 'left', field: 'unit' },
        { name: 'expression', label: '公式', align: 'left', field: 'expression' },
        { name: 'digit', label: '小数位数', align: 'left', field: 'digit' },
        { name: 'operations', label: '操作', align: 'left', field: 'operations' }
      ],
      pagination: {
        // 页码
        page: 1,
        // 每页条数
        rowsPerPage: 15,
        // 总条数
        rowsNumber: 0
      },
      selTab: '',
      tab: '',
      addDeviceDialog: false,
      addDeviceList: [],
      setProductDialog: false,
      exportLoading: false,
      form: {}
    }
  },
  watch: {
    tableDataAll: {
      deep: true,
      immediate: true,
      handler (val) {
        // this.pagination.rowsNumber = val.length
        this.$emit('changeData', val)
      }
    },
    tableDataByDevice: {
      deep: true,
      immediate: true,
      handler (val) {
        this.pagination.rowsNumber = val.length
      }
    },
    tabList: {
      deep: true,
      immediate: true,
      handler (val) {
        const deivceIds = val.map(item => item.deviceId)
        this.$emit('changeDeviceIds', deivceIds)
        if (val?.length && !this.selTab) {
          this.selTab = val[0].name
        }
      }
    },
    boxDriverId: {
      immediate: true,
      handler (val) {
        if (val) {
          this.getPointData()
        }
      }
    }
  },
  computed: {
    tableDataByDevice () {
      return this.tableDataAll.filter(item => item.deviceNum === this.selTab)
    },
    tableData () {
      return this.tableDataByDevice.slice((this.pagination.page - 1) * this.pagination.rowsPerPage, this.pagination.page * this.pagination.rowsPerPage)
    },
    columns () {
      let columnsAll = this.columnsAll
      if (this.isEnergy) {
        columnsAll = columnsAll.filter(item => item.name !== 'deviceTypeName')
      }
      if (this.isDetail) {
        return columnsAll.filter(item => item.name !== 'operations')
      }
      return columnsAll
    },
    tabList () {
      const result = [...this.addDeviceList]
      this.tableDataAll.forEach(item => {
        if (result.findIndex(re => re.name === item.deviceNum) === -1) {
          result.push({
            name: item.deviceNum,
            label: item.deviceName,
            deviceId: item.deviceId,
            productId: item.productId
          })
        }
      })
      return result.sort((a, b) => {
        const aStr = a.name.toString()
        const bStr = b.name.toString()
        return aStr.localeCompare(bStr)
      })
    },
    isEnergy () {
      return this.controllerType === '2'
    }
  },
  methods: {
    // 获取物模型的信息
    async getBoxProducts () {
      const { data } = await getBoxProducts()
      const deviceTypeOptions = []
      // eslint-disable-next-line no-unused-expressions
      data?.products?.forEach(item => {
        if (item.device_type === 'PLC') {
          deviceTypeOptions.push({
            label: item.name,
            value: item.product_id,
            common: item.is_common
          })
        }
      })
      // 处理通用物模型,将通用物模型放在最前
      const index = deviceTypeOptions.findIndex(item => item.common)
      if (index > -1) {
        const commonItem = deviceTypeOptions[index]
        deviceTypeOptions.splice(index, 1)
        deviceTypeOptions.unshift(commonItem)
      }
      this.deviceTypeOptions = deviceTypeOptions
      this.$emit('changeDeviceType', deviceTypeOptions)
    },
    getRepDataTypeByDataType (val) {
      if (!val) return null
      const string = ['2', '9']
      const int = ['1', '0', '3', '4', '5', '6', '10', '11']
      const double = ['7', '8']
      if (string.indexOf(val) > -1) {
        return 2
      } else if (int.indexOf(val) > -1) {
        return 1
      } else if (double.indexOf(val) > -1) {
        return 3
      }
    },
    // 获取点位信息
    async getPointData () {
      // 产品信息
      if (this.deviceTypeOptions.length === 0) {
        await this.getBoxProducts()
      }
      const reportTypeObj = {}
      const dataTypeObj = {}
      const deviceTypeObj = {}
      const dataTypeReportObj = {}
      reportTypeOption.forEach(reportType => {
        reportTypeObj[reportType.value] = reportType.label
      })
      dataTypeOption.forEach(dataType => {
        dataTypeObj[dataType.value] = dataType.label
      })
      dataTypeReportOption.forEach(dataType => {
        dataTypeReportObj[dataType.value] = dataType.label
      })
      this.deviceTypeOptions.forEach(deviceType => {
        deviceTypeObj[deviceType.value] = deviceType.label
      })
      if (this.isPreVersion) {
        if (!this.driverParams.boxNum) {
          return
        }
        this.isTableLoading = true
        getPlcDeviceByBoxId(this.driverParams.boxNum).then(res => {
          const data = res.data || []
          const ids = data.map(item => item.id)
          if (ids.length === 0) return
          getPlcPoint(ids).then(res => {
            this.tableDataAll = res.data.map(item => ({
              ...item,
              id: '__' + Math.random().toString(36).substr(2, 9),
              serviceTypeId: item.serviceTypeId ? item.serviceTypeId : '',
              reportTypeName: item.serviceTypeId ? `${reportTypeObj[item.repType]}(${item.serviceTypeId})` : `${reportTypeObj[item.repType]}`,
              dataTypeName: item.dataType ? `${dataTypeObj[item.dataType]}` : '',
              repDataType: item.repDataType ? item.repDataType : this.getRepDataTypeByDataType(item.dataType),
              repDataTypeName: item.repDataType ? `${dataTypeReportObj[item.repDataType]}` : this.getRepDataTypeByDataType(item.dataType) ? `${dataTypeReportObj[this.getRepDataTypeByDataType(item.dataType)]}` : '',
              deviceTypeName: item.productId ? `${deviceTypeObj[item.productId]}` : '',
              deviceName: `${item.deviceName}(${item.deviceNum})`
            }))
            if (this.tabList?.length && (!this.selTab || this.tabList.indexOf(this.selTab) === -1)) {
              this.selTab = this.tabList[0].name
            }
          })
        }).finally(() => {
          this.isTableLoading = false
        })
      } else {
        if (!this.boxDriverId) {
          return
        }
        this.isTableLoading = true
        getBindPoint(this.boxDriverId).then(res => {
          this.tableDataAll = res.data.map(item => ({
            ...item,
            id: '__' + Math.random().toString(36).substr(2, 9),
            serviceTypeId: item.serviceTypeId ? item.serviceTypeId : '',
            reportTypeName: item.serviceTypeId ? `${reportTypeObj[item.repType]}(${item.serviceTypeId})` : `${reportTypeObj[item.repType]}`,
            dataTypeName: item.dataType ? `${dataTypeObj[item.dataType]}` : '',
            deviceTypeName: item.productId ? `${deviceTypeObj[item.productId]}` : '',
            deviceName: `${item.deviceName}(${item.deviceNum})`,
            repDataType: item.repDataType ? item.repDataType : this.getRepDataTypeByDataType(item.dataType),
            repDataTypeName: item.repDataType ? `${dataTypeReportObj[item.repDataType]}` : this.getRepDataTypeByDataType(item.dataType) ? `${dataTypeReportObj[this.getRepDataTypeByDataType(item.dataType)]}` : '',
            partcountName: item.partcountType ? partcountObj[item.partcountType] : ''
          }))
          if (this.tabList?.length && (!this.selTab || this.tabList.indexOf(this.selTab) === -1)) {
            this.selTab = this.tabList[0].name
          }
        }).finally(() => {
          this.isTableLoading = false
        })
      }
    },
    // 删除点位
    deletePoint (row) {
      const index = this.tableDataAll.findIndex(item => item.id === row.id)
      this.tableDataAll.splice(index, 1)
    },
    // 新建或者编辑
    createOrEdit (type, form) {
      // 如果为计数A的话，设置partcountType默认值为1
      if (form && form.repType === '2' && form.serviceTypeId === 'A') {
        form.partcountType = form.partcountType ? form.partcountType + '' : '1'
      }
      this.$refs.addEditPointDialog.showDialog(form, type)
      if (form) {
        this.form = form
      }
    },
    // 添加数据
    addData (data) {
      const deviceInfo = this.tabList.find(item => item.name === this.selTab)
      data.deviceNum = this.selTab
      data.deviceName = deviceInfo?.label
      data.deviceId = deviceInfo?.deviceId
      if (data.repType === '2' && data.serviceTypeId === 'A' && data.partcountType) {
        data.partcountName = partcountObj[data.partcountType]
      } else {
        data.partcountType = ''
      }
      // 如果上报类型不为小数, 则小数位数不填
      if (data.repDataType + '' !== '3') {
        data.digit = ''
      }
      data.productId = deviceInfo.productId
      data.deviceTypeName = this.deviceTypeOptions.find(item => item.value === data.productId)?.label
      const info = {
        id: '__' + Math.random().toString(36).substr(2, 9),
        ...data,
        relaPoint: ''
      }
      this.tableDataAll.unshift(info)
    },
    // 编辑数据
    editData (data) {
      // 如果报警切换为H或者L
      const alarmHL = data.repType === '3' && data.serviceTypeId !== this.form.serviceTypeId
      // 如果报警切换为其他类型
      const alarmChange = this.form.repType === '3' && data.repType !== '3'
      // 如果实时数据切换为其他类型
      const pointChange = this.form.repType === '4' && data.repType !== '4'
      // 如果报警切换为其他类型
      if (alarmHL || alarmChange || pointChange) {
        data.relaPoint = ''
      }
      if (data.repType === '2' && data.serviceTypeId === 'A' && data.partcountType) {
        data.partcountName = partcountObj[data.partcountType]
      } else {
        data.partcountType = ''
      }
      // 如果上报类型不为小数, 则小数位数不填
      if (data.repDataType + '' !== '3') {
        data.digit = ''
      }
      // 如果实时数据切换为其他类型
      data.deviceNum = this.selTab
      data.deviceName = this.tabList.find(item => item.name === this.selTab)?.label
      data.deviceTypeName = this.deviceTypeOptions.find(item => item.value === data.productId)?.label
      const index = this.tableDataAll.findIndex(item => item.id === data.id)
      this.tableDataAll.splice(index, 1, data)
    },
    /**
     * on 分页组件的每页条数发生改变
     * @param val 每页条数
     */
    onPageSizeChange: function (val, page) {
      this.pagination.rowsPerPage = val
      page && (this.pagination.page = page)
    },

    /**
     * on 分页组件的页码发生改变
     * @param val 页码
     */
    onPageChange: function (val) {
      this.pagination.page = val
    },

    /**
     * 导入成功
     * @param val 导入完成地址
     */
    uploadUrlSuccess (val) {
      const params = {
        url: val
      }
      const deviceInfo = this.tabList.find(item => item.name === this.selTab)
      const reportTypeObj = {}
      const dataTypeObj = {}
      const deviceTypeObj = {}
      const dataTypeReportObj = {}
      reportTypeOption.forEach(reportType => {
        reportTypeObj[reportType.value] = reportType.label
      })
      dataTypeOption.forEach(dataType => {
        dataTypeObj[dataType.value] = dataType.label
      })
      dataTypeReportOption.forEach(dataType => {
        dataTypeReportObj[dataType.value] = dataType.label
      })
      this.deviceTypeOptions.forEach(deviceType => {
        deviceTypeObj[deviceType.label] = deviceType.value
      })
      const tableDataAllFilter = this.tableDataAll.filter(item => item.deviceNum !== this.selTab)
      if (this.isEnergy) {
        uploadEnergyPointTemplate(params).then(res => {
          const tableDataAll = res.data.map(item => ({
            ...item,
            id: '__' + Math.random().toString(36).substr(2, 9),
            serviceTypeId: item.serviceTypeId ? item.serviceTypeId : '',
            reportTypeName: item.serviceTypeId ? `${reportTypeObj[item.repType]}(${item.serviceTypeId})` : `${reportTypeObj[item.repType]}`,
            dataTypeName: item.dataType ? `${dataTypeObj[item.dataType]}` : '',
            deviceTypeName: item.productId,
            deviceName: deviceInfo?.label,
            deviceNum: this.selTab,
            deviceId: deviceInfo?.deviceId,
            productId: deviceTypeObj[item.productId],
            partcountName: item.partcountType ? partcountObj[item.partcountType] : '',
            repDataType: item.repDataType ? item.repDataType : this.getRepDataTypeByDataType(item.dataType),
            repDataTypeName: item.repDataType ? `${dataTypeReportObj[item.repDataType]}` : this.getRepDataTypeByDataType(item.dataType) ? `${dataTypeReportObj[this.getRepDataTypeByDataType(item.dataType)]}` : ''
          }))
          this.tableDataAll = [...tableDataAllFilter, ...tableDataAll]
        }).finally(() => {
          this.$refs.uploadBtn.closeUbscribeTopic()
        })
      } else {
        uploadPointTemplate(params).then(res => {
          const tableDataAll = res.data.map(item => ({
            ...item,
            id: '__' + Math.random().toString(36).substr(2, 9),
            serviceTypeId: item.serviceTypeId ? item.serviceTypeId : '',
            reportTypeName: item.serviceTypeId ? `${reportTypeObj[item.repType]}(${item.serviceTypeId})` : `${reportTypeObj[item.repType]}`,
            dataTypeName: item.dataType ? `${dataTypeObj[item.dataType]}` : '',
            deviceTypeName: item.productId,
            deviceName: deviceInfo?.label,
            deviceNum: this.selTab,
            deviceId: deviceInfo?.deviceId,
            productId: deviceTypeObj[item.productId],
            partcountName: item.partcountType ? partcountObj[item.partcountType] : '',
            repDataType: item.repDataType ? item.repDataType : this.getRepDataTypeByDataType(item.dataType),
            repDataTypeName: item.repDataType ? `${dataTypeReportObj[item.repDataType]}` : this.getRepDataTypeByDataType(item.dataType) ? `${dataTypeReportObj[this.getRepDataTypeByDataType(item.dataType)]}` : ''
          }))
          this.tableDataAll = [...tableDataAllFilter, ...tableDataAll]
        }).finally(() => {
          this.$refs.uploadBtn.closeUbscribeTopic()
        })
      }
    },

    /**
     * 删除tab列表
     * @param val
     */
    deleteTab (val) {
      const index = this.tabList.findIndex(item => item.name === val)
      this.$q.dialog({
        title: `<p class="dialog-notice-title"><i class="iconfont icontubiao-28"></i>
          设备删除后，该设备下的点位信息将一并删除，请确认</p>`,
        html: true,
        ok: {
          unelevated: true,
          label: '确认'
        },
        cancel: {
          unelevated: true,
          outline: true,
          label: '取消'
        }
      }).onOk(() => {
        this.tableDataAll = this.tableDataAll.filter(item => item.deviceNum !== val)
        this.addDeviceList = this.addDeviceList.filter(item => item.name !== val)
        this.$nextTick(() => {
          if (index > -1) {
            this.selTab = this.tabList[index - 1]?.name || this.tabList[index]?.name || ''
          } else {
            this.selTab = ''
          }
        })
      })
    },

    /**
     * 添加设备tab
     * @param val
     */
    addDevice (val) {
      const checkIndex = this.tabList.findIndex(item => item.name === val.name)
      if (checkIndex > -1) {
        this.$message.warning('设备已存在,不能重复添加')
        return
      }
      this.addDeviceDialog = false
      this.addDeviceList.push(val)
      this.selTab = val.name
    },

    /**
     * 打开下载模板
     */
    download () {
      if (this.isEnergy) {
        downloadEnergyPointTemplate().then(async res => {
          await this.$saveFileForBlob(res.data, '能耗点位(模板).xls')
          this.$message.success('数据请求成功,请保存文件')
        })
      } else {
        this.setProductDialog = true
      }
    },
    /**
     * 提交
     */
    submitDownload (val) {
      downloadPointTemplate(val.label, val.value).then(async res => {
        await this.$saveFileForBlob(res.data, 'PLC点位(模板).xls')
        this.$message.success('数据请求成功,请保存文件')
      }).finally(() => {
        this.setProductDialog = false
      })
    },
    /**
     * 导出excel
     */
    exportExcel () {
      const selDevice = this.tabList.find(item => item.name === this.selTab)
      if (!selDevice) return
      const params = {
        deviceId: selDevice.deviceId
      }
      this.exportLoading = true
      if (this.isEnergy) {
        exportEnergyPoint(params).then(async res => {
          await this.$saveFileForBlob(res.data, `能耗点位${selDevice.label}数据.xls`)
          this.$message.success('数据请求成功,请保存文件')
        }).finally(() => {
          this.exportLoading = false
        })
      } else {
        exportPlcPoint(params).then(async res => {
          await this.$saveFileForBlob(res.data, `PLC点位${selDevice.label}数据.xls`)
          this.$message.success('数据请求成功,请保存文件')
        }).finally(() => {
          this.exportLoading = false
        })
      }
    },
    onEdit (targetKey, action) {
      if (action === 'add') {
        this.addDeviceDialog = true
      } else {
        this.deleteTab(targetKey)
      }
    },
    toDetail () {
      const deviceInfo = this.tabList.find(item => item.name === this.selTab)
      this.$q.loading.show()
      getUserByDeviceId(deviceInfo.deviceId).then(res => {
        const row = res.data
        this.$router.push({
          path: '/main/status-monitor-v3/machine-list/machine-detail',
          query: {
            boxUcloudNum: this.driverParams.ucloudBoxNum,
            id: deviceInfo.deviceId,
            operatorName: row.operatorName,
            technicianName: row.technicianName,
            boxId: this.driverParams.boxNum,
            boxStrId: this.driverParams.boxNum,
            fromList: true,
            isPlc: 1
          }
        })
      }).finally(() => {
        this.$q.loading.hide()
      })
    }
  }
}
</script>

<style scoped lang="stylus">
.margin-r-5{
  margin-right: 5px;
}
.margin-l-5{
  margin-left: 5px;
}
>>>.container
  width 100%!important
.pagination {
  position initial
  padding-bottom 20px
}
>>>.ant-tabs-tab-active {
  color: rgb(95, 119, 253)!important;
}
</style>
